﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using Microsoft.Web.WebView2.Core;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Windows.Interop;

namespace MyCusTools
{
    public partial class Jupyter_UC: UserControl
    {
        public Jupyter_UC() // 构造函数
        {
            InitializeComponent();
        }

        #region Jupyter WebView创建运行环境+Jupyter线程执行
        /// <summary>
        /// Jupyter任务窗格建立独立的运行环境，在自定义任务窗格加载时(这个函数在InitializeComponent函数中绑定UC的Load事件)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void Cus_UserControl_Load(object sender, EventArgs e)
        {
            Create_JupyterWorkPath(); // 先检查jupyter的工作目录是不是存在，不存在则创建
            StartJupyterServerAsync(); // 异步jupyter的线程
            // 通过CoreWebView2Environment.CreateAsync手动控制环境路径
            try
            {
                // 创建目录
                var userDataFolder = Path.Combine(
                    Path.GetTempPath(),
                    "WebView_Jupyter",
                    Environment.UserName
                );
                Directory.CreateDirectory(userDataFolder);

                // 显式创建并运行环境
                var env = await CoreWebView2Environment.CreateAsync(
                    browserExecutableFolder: null,
                    userDataFolder: userDataFolder,
                    options: new CoreWebView2EnvironmentOptions()
                );
                await WebView_Jupyter.EnsureCoreWebView2Async(env);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"初始化失败: {ex.ToString()}");
            }
        }

        private Process _jupyterProcess; // jupyter线程
        private Process _jupyterServerProcess; // jupyter获取token的线程
        private string _jupyterToken = string.Empty; // jupyter的Token
        private string _jupyterWorkPath = @"D:\StudyFolder\JupyterWorkFolder";

        private void Create_JupyterWorkPath()
        {
            bool Jupyter_WorkPath_Is_Exists = Directory.Exists(_jupyterWorkPath);
            if (!Jupyter_WorkPath_Is_Exists) // 工作目录不存在则创建
            {
                DirectoryInfo directoryInfo = new DirectoryInfo(_jupyterWorkPath);
                directoryInfo.Create();
            }
        }

        private async void StartJupyterServerAsync()
        {
            
            _jupyterProcess = new Process();
            _jupyterProcess.StartInfo.FileName = "cmd.exe";
            _jupyterProcess.StartInfo.Arguments = "/c jupyter lab --port=8888 --no-browser";
            _jupyterProcess.StartInfo.WorkingDirectory = _jupyterWorkPath;
            _jupyterProcess.StartInfo.UseShellExecute = false; // 触发重定向，这个属性必须设置false
            _jupyterProcess.StartInfo.RedirectStandardOutput = true; // 重定向输出
            _jupyterProcess.StartInfo.RedirectStandardError = true; // 捕获错误流
            _jupyterProcess.StartInfo.CreateNoWindow = true;
            _jupyterProcess.EnableRaisingEvents = true; // 监听进程退出事件，确保资源释放
            _jupyterProcess.Exited += (sender, e) =>
            {
                _jupyterProcess.Dispose();
            };


            _jupyterServerProcess = new Process();
            _jupyterServerProcess.StartInfo.FileName = "jupyter";
            _jupyterServerProcess.StartInfo.Arguments = "server list";
            _jupyterServerProcess.StartInfo.UseShellExecute = false;
            _jupyterServerProcess.StartInfo.RedirectStandardOutput = true;
            _jupyterServerProcess.StartInfo.RedirectStandardError = true;
            _jupyterServerProcess.StartInfo.CreateNoWindow = true;
            _jupyterServerProcess.EnableRaisingEvents = true; // 监听进程退出事件，确保资源释放
            _jupyterServerProcess.Exited += (sender, e) =>
            {
                _jupyterServerProcess.Dispose();
            };

            _jupyterServerProcess.OutputDataReceived += OnJupyterOutputReceived;
            _jupyterServerProcess.ErrorDataReceived += OnJupyterErrorReceived;
            try
            {
                if (IsPortAvailable(8888))
                {
                    _jupyterProcess.Start();
                    //_jupyterProcess.WaitForExit(); // 需要等待进程结束，同步的
                    await Task.Delay(5000); // 第一次启动增加等待5s
                }
                await Task.Delay(3000); // 使用硬等待
                // 后续可以使用Jupyter Debug文件创建的形式判断server是否启动
                _jupyterServerProcess.Start();
                _jupyterServerProcess.BeginOutputReadLine();  // 开始异步读取输出
                _jupyterServerProcess.BeginErrorReadLine();
               
            }
            catch (Exception ex)
            {
                MessageBox.Show($"启动失败: {ex.Message}");
            }
        }

        private void OnJupyterOutputReceived(object sender, DataReceivedEventArgs e)
        {
            //MessageBox.Show($"Jupyter Output: {e.Data}");
            if (!string.IsNullOrEmpty(e.Data))
            {
                // 正则匹配 Token（示例：http://localhost:8888/lab?token=xxxx）
                var tokenMatch = Regex.Match(e.Data, @"token=([a-fA-F0-9]{32,})");

                if (tokenMatch.Success)
                {
                    _jupyterToken = tokenMatch.Groups[1].Value;
                    Invoke((Action)(() =>
                    {
                        WebView_Jupyter.Source = new Uri($"http://localhost:8888/lab?token={_jupyterToken}");
                        //MessageBox.Show(_jupyterToken);
                    }));
                }
            }
        }
        private void OnJupyterErrorReceived(object sender, DataReceivedEventArgs e)
        {
            if (!string.IsNullOrEmpty(e.Data))
                Debug.WriteLine($"Jupyter Error: {e.Data}");
        }

        // 确保端口未被占用
        private bool IsPortAvailable(int port)
        {
            var tcpListeners = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners();
            return !tcpListeners.Any(x => x.Port == port);
        }


        #endregion

    }
}